<!--

    Licensed to the Apache Software Foundation (ASF) under one
    or more contributor license agreements.  See the NOTICE file
    distributed with this work for additional information
    regarding copyright ownership.  The ASF licenses this file
    to you under the Apache License, Version 2.0 (the
    "License"); you may not use this file except in compliance
    with the License.  You may obtain a copy of the License at

      http://www.apache.org/licenses/LICENSE-2.0

    Unless required by applicable law or agreed to in writing,
    software distributed under the License is distributed on an
    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
    KIND, either express or implied.  See the License for the
    specific language governing permissions and limitations
    under the License.

-->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<title>Connecting Help in NetBeans: From Help Set Installation to Hooking up Context-Sensitive Help</title>
<link rel="stylesheet" href="../../../../../prose.css" type="text/css">
</head>

<body>
<p class="overviewlink"><a href="../package-summary.html">Overview</a></p>

<h1>Connecting Help in NetBeans: From Help Set Installation to Hooking up Context-Sensitive Help</h1>

<p>This document is designed to help NetBeans module writers with installing
help into the IDE and correctly setting
  up context-sensitive help for their modules. The document covers the following 
  topics:</p>

<ul>
  <li><a href="#intro">Introduction</a></li>
  <li><a href="#adding">Adding Help to GUI components</a><br>
    <ul>
      <li> <a href="#nodes">Explorer Nodes</a> </li>
      <li><a href="#wizards">Wizards</a> </li>
      <li><a href="#dialogs">Dialogs</a> </li>
      <li><a href="#propsheets">Property Sheets</a> <br>
      </li>
      <li><a href="#tabpropsheets">Tabbed Property Sheets</a> <br>
      </li>
      <li><a href="#props">Individual Properties</a> <br>
      </li>
      <li><a href="#propeditor">Custom Property Editors</a><br>
      </li>
      <li><a href="#tabpropeditors">Tabbed Custom Property Editors</a> <br>
      </li>
    </ul>
  </li>
  <li><a href="#toc-index">Merge Hints for TOC and Index</a><br>
  </li>
  <li><a href="#makeknown">Making the Help Set Known to the IDE</a></li>
  <li><a href="#putfiles">Where to Put Help Files in the Module Source</a> <br>
  </li>
  <li><a href="#notes">Additional Notes</a> <br>
    <ul>
      <li> <a href="#helpids">Making Help IDs Unique</a> <br>
      </li>
      <li><a href="#i18n">I18N of Help IDs</a><br>
      </li>
    </ul>
  </li>
</ul>

<h2><a name="intro">Introduction</a></h2>
<p>The IDE's architecture enables you to:</p>
<ul>
  <li> Create separate help sets and associate them with given modules.</li>
  <li> Specify the order in which the help sets are merged, which can affect 
the order in which topics appear within the table of contents.</li>
  <li> Associate an IDE component with a specific help topic by means of a help 
    ID for the component. When the user presses F1 or a Help button on the component, 
    the help is displayed in the JavaHelp viewer.</li>
  <li>Create a separate menu item for the help set</li>  
</ul>
<p>In order to take advantage of these help features, a NetBeans module writer 
  must be aware of different aspects of the NetBeans help system, specifically: 
</p>

<ul>
  <li> How to programmatically specify which help text to display for GUI components 
  </li>
  <li> How to declare the help set for the module so it will be found at runtime 
  </li>
  <li> Where to include help related files in the module source so it can be checked 
    into the CVS repository </li>
  <li> How to specify how the help set is built during the IDE's build process </li>
</ul>

<h2><a name="adding">Adding Help to GUI components</a></h2>
<p>There is an overview of adding help to various GUI NetBeans components in the
<a href="api.html#helpctx-context-help">JavaHelp Integration API</a>.
This section expands a bit on the information 
provided there.</p>

<h3><a name="nodes">Explorer Nodes</a></h3>
<p>If your node extends <code>AbstractNode</code> or one of its subclasses, you should 
  implement the <code>getHelpCtx</code> method to return a <a href="@org-openide-util-ui@/org/openide/util/HelpCtx.html"> 
  <code>HelpCtx</code></a> for the node. The <code>HelpCtx</code> includes the specific 
  Help ID for the help topic for this node. If the node is selected in the explorer 
  and the user hits the F1 key, then the help associated with this node will be 
  displayed. </p>

<pre>
<span class="keyword">public</span> <span class="keyword">class</span> <span class="type">MyNode</span> <span class="keyword">extends</span> <span class="type">AbstractNode</span>{
    <span class="keyword">public</span> <span class="type">HelpCtx</span> <span class="function-name">getHelpCtx</span>() {
        <span class="keyword">return</span> <span class="keyword">new</span> <span class="type">HelpCtx</span>(<span class="string">"org.netbeans.modules.xml.tree.nodes.XMLDataNode"</span>);   
    }
    <span class="comment">// other methods...
</span>}
</pre>

<h3><a name="wizards">Wizards</a></h3>
<p>Wizards are basically a series of Swing Components that are displayed via a 
  <a href="@org-openide-dialogs@/org/openide/WizardDescriptor.Iterator.html"> 
  <code>WizardDescriptor.Iterator</code></a> object. The object that the developer 
  creates must implement the <a href="@org-openide-dialogs@/org/openide/WizardDescriptor.Panel.html"> 
  <code>WizardDescriptor.Panel</code></a> interface which includes a method that the 
  developer implements to return the actual Swing Component that is to be displayed 
  (usually a <code>JPanel</code> is returned). Additionally, the developer must implement 
  the <code>getHelp</code> method and return a <code>HelpCtx</code> for this particular 
  wizard step. By default, the <i>Help</i> button is displayed on the resulting 
  <code>JDialog</code> and when the user selects this <i>Help</i> button, the <code>getHelp</code> 
  method is called for the currently displayed <code>WizardDescriptor.Panel</code> 
  object. </p>

<pre>
<span class="keyword">public</span> <span class="keyword">class</span> <span class="type">MyWizardPanel</span> <span class="keyword">implements</span> <span class="type">WizardDescriptor.Panel</span> {
    <span class="keyword">private</span> <span class="type">JPanel</span> <span class="variable-name">p</span>;
    <span class="keyword">public</span> <span class="type">Component</span> <span class="function-name">getComponent</span>() {
	<span class="keyword">if</span> (p == <span class="constant">null</span>) {
	    p = <span class="keyword">new</span> <span class="type">JPanel</span>();
            p.setLayout(<span class="keyword">new</span> <span class="type">BorderLayout</span>());
            p.add(<span class="comment">/* etc. */</span>);
        }
	<span class="keyword">return</span> p;
    }
    <span class="keyword">public</span> <span class="type">HelpCtx</span> <span class="function-name">getHelp</span>() {
        <span class="keyword">return</span> <span class="keyword">new</span> <span class="type">HelpCtx</span>(<span class="string">"org.netbeans.modules.xml.core.wizard.DocumentPanel"</span>);  
    }
    <span class="comment">// other methods...
</span>}
</pre>

<h3><a name="dialogs">Dialogs</a></h3>
<p>There are two different ways in which you can set help on a NetBeans dialog. 
  If you wish to display a dialog of some sort, you typically create the Swing 
  components you wish to display and then create a <a href="@org-openide-dialogs@/org/openide/DialogDescriptor.html"> 
  <code>DialogDescriptor</code></a> object which is a NetBeans object that is used 
  to describe the behavior or the dialog. To display help: </p>
<ol>
  <li> Specify the help on the <code>DialogDescriptor</code> object - As a rule, setting 
    the help ID on the <code>DialogDescriptor</code> is the preferred way to set a 
    help ID for a dialog. There are a couple of ways to do this: 
    <ul>
      <li> Use one of the
          <a href="@org-openide-dialogs@/org/openide/DialogDescriptor.html#DialogDescriptor-java.lang.Object-java.lang.String-boolean-int-java.lang.Object-int-org.openide.util.HelpCtx-java.awt.event.ActionListener-"><code>DialogDescriptor</code> constructors</a>
          that includes
        a <code>HelpCtx</code>.
      </li>
      <li> Call <code>setHelpCtx</code> on the previously created <code>DialogDescriptor</code>: 

<pre>
<span class="type">DialogDescriptor</span> <span class="variable-name">dd</span> = <span class="keyword">new</span> <span class="type">DialogDescriptor</span>(...);
dd.setHelpCtx(<span class="keyword">new</span> <span class="type">HelpCtx</span>(<span class="string">"dialog_help_id"</span>));    
</pre>

      </li>
    </ul>
  </li>
  <li> Set the help ID string on the displayed Swing Component - You'll notice 
    that the <code>DialogDescriptor</code> constructor takes an <code>Object</code> which 
    is typically the Swing Component to display in the <code>JDialog</code>. If you 
    set the help ID string property on the Swing component, then this help id 
    will be used as the help id for the <code>JDialog</code> and the corresponding 
    help will be displayed if the user selects the <i>Help</i> button. 

<pre>
<span class="type">JPanel</span> <span class="variable-name">p</span> = <span class="keyword">new</span> <span class="type">JPanel</span>();
<span class="comment">// ...add Swing components to p ...
</span>HelpCtx.setHelpIDString(p, <span class="string">"panel_help_id"</span>);   
<span class="type">DialogDescriptor</span> <span class="variable-name">dd</span> = <span class="keyword">new</span> <span class="type">DialogDescriptor</span>(p, <span class="string">"Dialog Title"</span>);
</pre>

  </li>
</ol>
<p>If you do not supply a <code>HelpCtx</code> object for the <code>DialogDescriptor</code>
or set the help ID string for the displayed Swing Component, then no <i>Help</i> 
button will be displayed on the <code>JDialog</code> that is displayed for this <code>DialogDescriptor</code>.</p>
<h3><a name="propsheets"></a>Property Sheets </h3>
<p>When creating a Property Sheet, the developer creates a <a href="@org-openide-nodes@/org/openide/nodes/Sheet.Set.html"> 
  <code>Sheet.Set</code></a> object. To populate the <code>Sheet.Set</code> the developer 
  creates and adds a number of <a href="@org-openide-nodes@/org/openide/nodes/Node.Property.html"> 
  <code>Node.Property</code></a> objects. To display help for the Property Sheet, 
  you must call the <code>setValue</code> method and set the <code>helpID</code> property: 
</p>

<pre>
<span class="type">Sheet</span> <span class="variable-name">sheet</span> = Sheet.createDefault();
<span class="type">Sheet.Set</span> <span class="variable-name">ps</span> = sheet.get(Sheet.PROPERTIES);
ps.setValue(<span class="string">"helpID"</span>, <span class="string">"org.netbeans.modules.xml.tree.nodes.XMLDataNode.Properties"</span>);  
</pre>

<h3><a name="tabpropsheets">Tabbed Property Sheets</a></h3>
<p> Property sheets can actually contain multiple tabs, each having their own 
  help associated with them. The method described above to set the help id of 
  a Property Sheet still applies, the only difference is the way in which the 
  additional Property Sheet is created: </p>

<pre>
<span class="type">Sheet</span> <span class="variable-name">sheet</span> = Sheet.createDefault();
<span class="type">Sheet.Set</span> <span class="variable-name">referenceTab</span> = <span class="keyword">new</span> <span class="type">Sheet.Set</span>();
referenceTab.setValue(<span class="string">"helpID"</span>, <span class="string">"org.netbeans.modules.xml.tree.nodes.XMLDataNode.ReferenceProperties"</span>);  
referenceTab.setName(<span class="string">"referenceTab"</span>); <span class="comment">// NOI18N
</span>sheet.put(referenceTab);
</pre>

<h3><a name="props">Individual Properties</a></h3>
<p> You can also set an individual help ID for each property (<code>Node.Property</code>) 
  in a property sheet. Presently Sun Java Studio and NetBeans help is not provided on a per-property 
  basis - help on individual properties is provided in the form of a tooltip. 
</p>
<h3><a name="propeditor"></a>Custom Property Editors</h3>
<p>Some Properties displayed on a Property Sheet require a custom editor. The 
  user accesses the editor by selecting the "..." button on an entry for a specific 
  Property when the user selects that Property. The developer of the custom editor 
  provides a Swing Component (typically a JPanel) which is ultimately displayed 
  in a <code>JDialog</code>. If Help is to be supplied on the resulting <code>JDialog</code>, 
  then the help ID string of the supplied Swing Component must be set. </p>

<pre>
<span class="keyword">public</span> <span class="type">MyPropertyEditor</span> <span class="keyword">extends</span> <span class="type">PropertyEditorSupport</span>{
    <span class="keyword">public</span> <span class="type">Component</span> <span class="type">TreeNodeFilterCustomEditor</span>() {
	<span class="type">JPanel</span> <span class="variable-name">p</span> = <span class="keyword">new</span> <span class="type">JPanel</span>();
	<span class="comment">// ...add Swing components to p...
</span>	HelpCtx.setHelpIDString(p, <span class="string">"org.netbeans.modules.xml.tax.beans.editor.TreeNodeFilterCustomEditor"</span>);   
	<span class="keyword">return</span> p;
    }
    <span class="comment">// other methods...
</span>}
</pre>

<h3><a name="tabpropeditors"><b>Tabbed Custom Property Editor</b>s</a></h3>
<p>Some Custom Property Editors display a number of tabs. Depending on the tab 
  that is displayed, different Help may need to be displayed. In this case, you 
  should set the help ID on the property editor's JTabbedPane. If you want the 
  help ID to change when the user switches tabs, then you should listen for changes 
  in the selected tab, and change the ID on the JTabbedPane each time. 
<p>For NetBeans 3.4 and earlier, you can set help IDs on tabs as shown in this example:
<p>

<pre>
<span class="keyword">class</span> <span class="type">MyTabPane</span> <span class="keyword">extends</span> <span class="type">JTabbedPane</span> <span class="keyword">implements</span> <span class="type">ChangeListener</span> {
    <span class="keyword">private</span> <span class="type">HelpCtx</span>[] <span class="variable-name">helps</span> = <span class="keyword">new</span> <span class="type">HelpCtx</span>[3];
    <span class="keyword">public</span> <span class="type">MyTabPane</span>() {
        add(<span class="keyword">new</span> <span class="type">Panel1</span>());
        helps[0] = <span class="keyword">new</span> <span class="type">HelpCtx</span>(<span class="string">"help_1"</span>);
        <span class="comment">// etc.
</span>        stateChanged(<span class="constant">null</span>);
        addChangeListener(<span class="keyword">this</span>);
    }
    <span class="keyword">public</span> <span class="type">void</span> <span class="function-name">stateChanged</span>(<span class="type">ChangeEvent</span> <span class="variable-name">ignore</span>) {
        HelpCtx.setHelpIDString(<span class="keyword">this</span>, helps[getSelectedIndex()]);
    }
}
</pre>

<p>In NetBeans releases later than 3.4, you can use the <code>HelpCtx.Provider</code> to simplify 
  the process, as shown in the following example:</p>

<pre>
<span class="keyword">class</span> <span class="type">MyTabPane</span> <span class="keyword">extends</span> <span class="type">JTabbedPane</span> <span class="keyword">implements</span> <span class="type">HelpCtx.Provider</span> {
    <span class="keyword">private</span> <span class="type">HelpCtx</span>[] <span class="variable-name">helps</span> = <span class="keyword">new</span> <span class="type">HelpCtx</span>[3];
    <span class="keyword">public</span> <span class="type">MyTabPane</span>() {
        add(<span class="keyword">new</span> <span class="type">Panel1</span>());
        helps[0] = <span class="keyword">new</span> <span class="type">HelpCtx</span>(<span class="string">"help_1"</span>);
	<span class="comment">// etc.
</span>    }
    <span class="keyword">public</span> <span class="type">HelpCtx</span> <span class="function-name">getHelpCtx</span>() {
	<span class="keyword">return</span> helps[getSelectedIndex()];
    }
}
</pre>

<h2><a name="toc-index">Merge Hints for TOC and Index</a></h2>
<p>In NetBeans IDE 3.6, the help system has been upgraded to use v. 2.0 of JavaHelp 
software. The most visible benefit of the upgrade is better merging of TOC and index. 
NetBeans IDE uses the Unite-Append merge type for the table of contents and the Sort 
merge type for the index. These merge types are set in the master help set and 
propogate to any help sets that merge into the product, unless those help sets 
override them with other merge types. For more information on merge types, see the 
<a href="https://docs.oracle.com/cd/E19253-01/819-0913/819-0913.pdf">JavaHelp release 
notes.</a></p>

<p>The biggest resulting impact for module authors is the need to more carefully 
 design TOCs and indexes so that entries from different help sets merge 
 comprehensibly for users. Here are some general tips and rules of thumb:</p>
<ul>
 <li>Use the most recent revision of 
<a href="https://github.com/emilianbold/netbeans-releases/tree/master/usersguide/javahelp/org/netbeans/modules/usersguide/ide-idx.xml">
 the usersguide module index</a> as a guide for your indexing conventions to make your entries fit in 
 seamlessly.</li>
<li><i>DO NOT</i> use manual separators in your indexes, 
(e.g. &lt;indexitem text="-A-"&gt;&lt;/indexitem&gt;). These are superfluous 
with merged indexes are suspected of triggering a bug in JH that crashes the 
help system - see <a href="https://bz.apache.org/netbeans/show_bug.cgi?id=39966">
Issuezilla bug 39966</a>.</li>
<li>Any TOC or index entry that contains sub-entries should have no 
<samp>target</samp> attribute. This rule has been adopted because it is not 
possible to provide useful topics for every "bucket" and users should have a 
consistent experience as to when to expect a topic to display. If you feel that 
 there is a useful introductory topic for a TOC bucket, make that topic the 
 first entry in the bucket and call it "About". You can </li>

  <li>If you would like to insert entries into an existing TOC bucket, check 
  the most recent revision of the 
<a href="https://github.com/emilianbold/netbeans-releases/tree/master/usersguide/javahelp/org/netbeans/modules/usersguide/ide-toc.xml">
 the usersguide module TOC</a>.</li>
 <li>If you organize your table of contents so that "Core IDE Help" is your 
first-level TOC item, your help set will be slotted in under second level buckets 
created by the usersguide module. Also, this ensures your real top level topics are 
not expanded in the JH viewer (by default, the JH viewer shows two levels of topics 
when first opened), thus leaving more room in the first screenful of the 
help viewer for other modules' high-level topics. The TOC for such a module might 
look like the following:

<pre>
&lt;?xml version='1.0' encoding='ISO-8859-1'  ?&gt;
&lt;!DOCTYPE toc PUBLIC "-//Sun Microsystems Inc.//DTD JavaHelp TOC Version 1.0//EN"
         "http://java.sun.com/products/javahelp/toc_1_0.dtd"&gt;
&lt;toc version="1.0"&gt;
&lt;tocitem text="Core IDE Help"&gt;
    &lt;tocitem text="HTTP Monitor"&gt;
        &lt;tocitem text="Monitoring Data Flow on the Web Server" target="ctx_monitorintro" /&gt; 
	    &lt;tocitem text="Viewing HTTP Monitor Data Records" target="monitor_view" /&gt; 
	    &lt;tocitem text="Using the HTTP Monitor Toolbar" target="monitor_sort" /&gt;
	    &lt;tocitem text="Editing and Replaying Monitor Data Records" target="monitor_resend" /&gt; 
	    &lt;tocitem text="Saving HTTP Monitor Data Records" target="monitor_store" /&gt;  
	    &lt;tocitem text="Deleting HTTP Monitor Data Records" target="monitor_delete" /&gt;
            &lt;tocitem text="Deploying the HTTP Monitor for a Web Module" target="monitor_servconfig" /&gt;
        &lt;/tocitem&gt;
    &lt;/tocitem&gt;
&lt;/toc&gt;&lt;</pre>
 </li>
</ul>

<h2><a name="makeknown">Making the Help Set Known to the IDE</a></h2>
<p>In order to use the result help set within the IDE at runtime, a couple of things
need to be added to various files associated with the module. These are outlined 
in part in the <a href="api.html#helpctx-layer">reference documentation</a>.
This description assumes you are using a NetBeans module project.</p>

<p>A module's help set should be defined by creating a <code>package-info.java</code> file in the same package as the help set
    and adding the <code>@HelpSetRegistration</code> annotation to it. You will want to specify a position for the help set;
    this mainly affects the order into which help sets are merged into the table of contents.

<h2><a name="putfiles">Where to Put Help Files in the Module Source</a></h2>
<p>Help files should be kept under the regular <samp>src</samp> subdirectory
  off of the module root directory. Like source code, all JavaHelp documentation 
  must be placed into a globally unique package to avoid conflicts. If two modules 
  put help files into the same package, it will result in broken links.
  You should therefore use a distinctive "package"
  name prefix. It is conventional to use <code><em>module.code.name.base</em>.docs</code>,
  e.g. for a module named <code>org.netbeans.modules.foo</code>, place the JavaHelp
  into <code>org.netbeans.modules.foo.docs</code> (plus perhaps subpackages).

<h2><a name="notes">Additional Notes</a></h2>
<p>This section includes any additional comments or issues regarding Help for IDE
modules.</p>
<ul>

  <li><a name="helpids"></a> <b>Making Help IDs Unique</b> - When a Help request 
    is initiated with a specific Help ID, the code that looks for the corresponding 
    html file to display starts checking the help sets that have been loaded. As 
    soon as a match is made, the html file is loaded in the JavaHelp viewer. There 
    is no checking to see if the help set matches the module from which the request 
    was made. So, for example, if you define a Help ID such as <samp>node_help</samp> and 
    include that in two different help sets, when this Help is requested the first 
    help set in which this ID is found will be used as the source for the corresponding 
    html file. 
    <p>It is therefore necessary for all Help IDs to be unique. The best way to 
      avoid collisions to preface all Help IDs with the standard package name 
      of the module it comes from. Thus for the Execution tabs of the property 
      sheet for a form object node, you should set the help ID to
      <samp>org.netbeans.modules.form.FormDataObject.executionTabProperties</samp>
      or similar.
      <br>
      <br>
  </li>

  <li><a name="i18n"></a><b>I18N of Help IDs -</b> All of the <code>HelpCtx</code> 
    methods that take strings as parameters are included in the IDE's list of 
    NOI18N patterns and therefore are not internationalized. You do not need to 
    add <samp>//&nbsp;NOI18N</samp> to lines containing these strings.
  </li>

</ul>

<p>
Questions or comments? Send to nbdev.
</p>

<hr>
<p>@FOOTER@</p>
</body>
</html>
